package jourre;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author: gcr
 * @Date: 2022-5-31 13:44
 */
public class JourUtils {
    // 这个工具类主要是计算得分用的  和本目录的JourCacu 使用

    private static final int DEF_DIV_SCALE = 3;

    //保留两位小数
    public static double getdoubleValue(double value) {
        try {
            BigDecimal bigDecimal = new BigDecimal(value);
            double d = bigDecimal.setScale(5, RoundingMode.HALF_UP).doubleValue();
            return d;
        } catch (Exception e) {
            return 0.001;
        }
    }

    //提供（相对）精确的除法运算，当发生除不尽的情况时
    //精确到小数点后10位的数字四舍五入
    public static double div(double v1, double v2) {
        try {
            BigDecimal b1 = BigDecimal.valueOf(v1);
            BigDecimal b2 = BigDecimal.valueOf(v2);
            return b1.divide(b2, DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
        } catch (Exception e) {
            return 0.001;
        }

    }

    // int 进行处理
    public static double divInt(int v1, int v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.divide(b2, DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    // 对Map进行排序，此排序为最大的在前面，输入一个map，再返回一个排序后的新map，String, Double类型
    public static Map<String, Double> mapSortValue(Map<String, Double> mapName) {
        Map<String, Double> result = new LinkedHashMap<>();
        mapName.entrySet().stream()
                .sorted(Map.Entry.<String, Double>comparingByValue()
                        .reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        return result;
    }

    // 获取map value 最大的
    public static Double getMapMaxValue(Map<String, Double> mapName) {
        if (mapName == null || mapName.size() == 0) {
            return 0.0;
        }
        Map<String, Double> result = new LinkedHashMap<>();
        mapName.entrySet().stream()
                .sorted(Map.Entry.<String, Double>comparingByValue()
                        .reversed()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        List<Double> values = result.values().stream().collect(Collectors.toList());
        Double aDouble = values.get(0);
        return aDouble;

    }

    // 获取map value 最小的
    public static Double getMapMinValue(Map<String, Double> mapName) {
        Map<String, Double> result = new LinkedHashMap<>();
        mapName.entrySet().stream().sorted(Map.Entry.<String, Double>comparingByValue()).forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        List<Double> values = result.values().stream().collect(Collectors.toList());
        Double aDouble = values.get(0);
        return aDouble;

    }

    // 根据最大值计算 和权重 计算相对得分返回数据
    public static Map<String, Double> computeMapWithMaxValue(Map<String, Double> mapName, Double score) {
        Map<String, Double> result = new LinkedHashMap<>();
        Double mapMaxValue = getMapMaxValue(mapName);

        mapName.forEach((k, v) -> {
            Double aDouble = countScore(v, score, mapMaxValue);

            result.put(k, aDouble);
        });
        return mapSortValue(result);

    }

    // 最大值max：满分full = 当前值now：X，X 为当前值相对应的得分，公式为：X = now * full / max

    /**
     * 计算相对分数 最大值除以满分 等于 当前值 除以 当前得分 也就是 等于 当前值 乘以最大得分 除以最大值就是得分
     *
     * @param now  当前值
     * @param full 满分得分
     * @param max  最大值
     * @return
     */
    public static Double countScore(Double now, Double full, Double max) {
        if (max != 0.0) {
            return div(mul(now, full), max);
        }
        return 0.0;
    }

    // int 进行处理

    /**
     * 进行根据数量得出百分比 v1  基数 v2 新数
     *
     * @param v1 基数
     * @param v2 新数
     * @return
     */
    public static double divIntScore(int v1, int v2) {
        int s = v2 - v1;
        if (s == 0) {
            return 0.0;
        }
        if (v1 == 0) {
            return 0.001;
        }
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(s);

        return b2.divide(b1, DEF_DIV_SCALE, BigDecimal.ROUND_HALF_UP).doubleValue();
    }

    public static void main(String[] args) {
        int d1 = 4;
        int d2 = 3;
        double div = divIntScore(d1, d2);
        System.out.println(div);
    }


    //提供精确的加法运算
    public static double add(double v1, double v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.add(b2).doubleValue();
    }

    //精确的减法运算
    public static double sub(double v1, double v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.subtract(b2).doubleValue();
    }

    //精确的乘法运算
    public static double mul(double v1, double v2) {
        BigDecimal b1 = BigDecimal.valueOf(v1);
        BigDecimal b2 = BigDecimal.valueOf(v2);
        return b1.multiply(b2).doubleValue();
    }

    // 归一化数据

    /**
     * 归一化
     * <p>
     * 两个区间
     * 一个 1-100 第二个 65-90 已知在 第二个区间值是81 求 81 这个值在第一个区间是多少
     * 90 - 81(A)        100-x
     * ------   =   --------
     * 90 - 65(B)      100-1(C)
     * 就是最大值减去得分值 除以这个区间长度 等于 另一个区间最大值 减去x 除以区间长度
     *
     * @param sourceMax 原始区间最大值
     * @param sourceMin 原始区间最小值
     * @param toMax     目标最大值
     * @param toMin     目标最小值
     * @param exist     已知值
     * @return tox      目标区间所求值x
     */
    public static double forceUnifyScore(double sourceMax, double sourceMin, double toMax, double exist, double toMin) {
        double B = Math.abs(sourceMax - sourceMin);
        double A = Math.abs(sourceMax - exist);
        double C = Math.abs(toMax - toMin);
        double res = takeThreeDigits(Math.abs(toMax - div((A * C), B)));
        return res;
    }

    // 取小数点后4位
    public static double takeThreeDigits(double d) {
        BigDecimal bd = new BigDecimal(d);
        BigDecimal bd2 = bd.setScale(3, RoundingMode.HALF_UP);
        return Double.parseDouble(bd2.toString());
    }

}
